home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / nhclb120.zoo / ttydriv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  7.3 KB  |  296 lines

  1. /* TTY input driver */
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include "config.h"
  5. #include "global.h"
  6. #include "session.h"
  7.  
  8. extern unsigned char escape;    /* default escape character is ^] */
  9.  
  10. #define    TTY_LIT    0        /* Send next char literally */
  11. #define    TTY_RAW    1
  12. #define TTY_COOKED    2
  13. /* TTY_ESC is escape char seen */
  14. #define TTY_ESC 3
  15.  
  16. int ttymode = TTY_COOKED;
  17. int ttyecho=1;
  18. #define    TTY_NOECHO    0
  19. #define    TTY_ECHO    1
  20.  
  21. #ifdef    FLOW
  22. int ttyflow=1;
  23. #endif
  24.  
  25. #define    LINESIZE    256
  26.  
  27. #define CTLR    18
  28. #define    CTLU    21
  29. #define    CTLV    22
  30. #define    CTLW    23
  31. #define    CTLZ    26
  32. #define    RUBOUT    127
  33.  
  34. /*
  35.  * First, some general explanation.
  36.  * raw and cooked are used with the usual meaning, but they don't
  37.  * involve any change in TTY modes.  Rather, the tty is set into
  38.  * a raw mode, and cooked mode is implemented by doing our own
  39.  * editing here.  The only TTY mode we normally toggle is flow control.
  40.  *
  41.  * This code also handles telnet special characters.  It could be
  42.  * done in telnet, but it turns out to be easier to code it here.
  43.  *
  44.  * Note that raw mode is either TTY_RAW or TTY_ESC, and cooked
  45.  * is either TTY_COOKED or TTY_LIT.  TTY_ESC and TTY_LIT are special
  46.  * substates used when a special character has been seen.
  47.  */
  48.  
  49. raw()
  50. {
  51.     /* 
  52.      * TTY_ESC is part of cooked mode, so if it's set, leave it.
  53.      */
  54.     if (ttymode != TTY_ESC)
  55.         ttymode = TTY_RAW;
  56. #ifdef    ATARI_ST
  57.     set_stdout(ttymode);    /* CR/LF vs LF madness...  -- hyc */
  58. #endif
  59. }
  60.  
  61. cooked()
  62. {
  63.     /* 
  64.      * TTY_LIT is part of cooked mode, so if it's set, leave it.
  65.      */
  66.     if (ttymode != TTY_LIT)
  67.         ttymode = TTY_COOKED;
  68. #ifdef    ATARI_ST
  69.     set_stdout(ttymode);
  70. #endif
  71. }
  72.  
  73. void
  74. echo()
  75. {
  76.     ttyecho = TTY_ECHO;
  77. }
  78.  
  79. void
  80. noecho()
  81. {
  82.     ttyecho = TTY_NOECHO;
  83. }
  84.  
  85. /*
  86.  * Accept characters from the incoming tty buffer and process them
  87.  * (if in cooked mode) or just pass them directly (if in raw mode).
  88.  * Returns the number of characters available for use; if non-zero,
  89.  * also stashes a pointer to the character(s) in the "buf" argument.
  90.  *
  91.  * This routine is called whenever a character is input.
  92.  * When in cooked mode, returns zero until we've got a whole line
  93.  * or there's some other reason to want to activate.
  94.  *
  95.  * This routine performs the mode switch to conversational mode.
  96.  * If this becomes a problem, perhaps we could return a negative
  97.  * number or some other special code.
  98.  */
  99.  /*Control-R added by df for retype of lines - useful in Telnet */
  100.  /*Then df got impatient and added Control-W for erasing words  */
  101.  /* Control-V for the literal-next function, slightly improved
  102.   * flow control, local echo stuff -- hyc */
  103. int
  104. ttydriv(c,buf)
  105. unsigned char c;
  106. unsigned char **buf;
  107. {
  108.     static unsigned char linebuf[LINESIZE];
  109.     static unsigned char *cp = linebuf;
  110.     unsigned char *rp ;
  111.     int cnt;
  112.     int seenprint;
  113.  
  114.     if(buf == (unsigned char **)0 )  /* was this NULL for the ST ? */
  115.         return 0;    /* paranoia check */
  116.  
  117.     cnt = 0;
  118.     switch(ttymode){
  119.     
  120.     /* TTY_LIT means we've seen a ^V in cooked mode. */
  121.     case TTY_LIT:
  122.         ttymode = TTY_COOKED;    /* Reset to cooked mode */
  123.         *cp++ = c;
  124.         if(cp >= &linebuf[LINESIZE]){
  125.               cnt = cp - linebuf;
  126.               cp = linebuf;
  127.         }
  128.         break;
  129.  
  130.     /* TTY_ESC means we've seen the escape character in raw mode. */
  131.     /* Raw mode is only used by telnet, so we can safely generate IAC's */
  132.     case TTY_ESC:
  133.         ttymode = TTY_RAW;
  134.         if (c == escape)
  135.             *cp++ = c;
  136.         else switch(c & 0x1f) {
  137. /*BRK*/            case '\002':  *cp++ = 255; *cp++ = 243; break; 
  138. /*IP*/            case '\003':  *cp++ = 255; *cp++ = 244; break;
  139. /*AO*/            case '\017':  *cp++ = 255; *cp++ = 245; break;
  140. /*AYT*/            case '\024':  *cp++ = 255; *cp++ = 246; break;
  141. /*EC*/            case '\010':  *cp++ = 255; *cp++ = 247; break;
  142. /*EL*/            case '\025':  *cp++ = 255; *cp++ = 248; break;
  143.             case '\030':    printf("\r\n");    cmdmode(); break;
  144.             case '\037':
  145.            printf("\r\n");
  146.            printf("Type the escape character followed by\r\n");
  147.            printf("  escape character - send a real escape character\r\n");
  148.            printf("  x or ^x - return to command mode\r\n");
  149.            printf("  b or ^b - send break\r\n");
  150.            printf("  c or ^c - send interrupt process\r\n");
  151.            printf("  o or ^o - abort output\r\n");
  152.            printf("  t or ^t - are you there?\r\n");
  153.            printf("  h or ^h - send telnet erase character\r\n");
  154.            printf("  u or ^u - send telnet erase line\r\n");
  155.            printf("  ?       - print this help message\r\n");
  156.                      break;
  157.         }
  158.         cnt = cp - linebuf;
  159.         cp = linebuf;
  160.         break;
  161.     case TTY_RAW:
  162.         if (c == escape) {
  163.             ttymode = TTY_ESC;
  164.             break;
  165.         }
  166.         /* 
  167.          * More telnet-specific stuff.  There's some debate
  168.          * what to do with CR.  In theory a telnet end of
  169.          * line is CR LF, so Cisco turns CR into CR LF.  But
  170.          * experience shows that with full duplex systems
  171.          * CR 0 (which means a real CR character) is safer.
  172.          * Some Unix systems turn CR LF into LF.  Presumably
  173.          * on systems where CR doesn't make sense we'll be
  174.          * in half-duplex.  Our half-duplex code does use CR LF
  175.          */
  176.         switch(c) {
  177.         case '\r':  /* CR must be sent as CR 0 or CR LF */
  178.             *cp++ = c;
  179.             c = '\0';
  180.             break;
  181.         case 0xff: /* IAC must be doubled */
  182.             *cp++ = c;
  183.             break;
  184.         }
  185.         *cp++ = c;
  186.         cnt = cp - linebuf;
  187.         cp = linebuf;
  188.         break;
  189.     case TTY_COOKED:
  190.         /* Perform cooked-mode line editing */
  191.         if (mode == CONV_MODE) { /* should really check for telnet */
  192.           if (c == escape) {
  193.             printf("\r\n"); cmdmode(); cp = linebuf; goto endline;
  194.           } else switch(c & 0x7f) {
  195.             case CTLV: ttymode = TTY_LIT; goto nochar;
  196. /*BRK*/            case '\002':  *cp++ = 255; *cp++ = 243; goto endline;
  197. /*IP*/            case '\003':  *cp++ = 255; *cp++ = 244; goto endline;
  198. /*AO*/            case '\017':  *cp++ = 255; *cp++ = 245; goto endline;
  199. /*AYT*/            case '\024':  *cp++ = 255; *cp++ = 246; goto endline;
  200.           }
  201.         }
  202. #ifdef PC9801
  203.         switch(c){
  204. #else
  205.         switch(c & 0x7f){
  206. #endif
  207.         case '\r':    /* CR and LF are equivalent */
  208.         case '\n':
  209.             *cp++ = '\r';
  210.             *cp++ = '\n';
  211.             printf("\n");
  212. endline:
  213.             cnt = cp - linebuf;
  214.             cp = linebuf;
  215. nochar:
  216.             break;
  217.         case RUBOUT:
  218.         case '\b':        /* Backspace */
  219.             if(cp != linebuf){
  220.                 cp--;
  221.                 if (ttyecho)
  222.                     printf("\b \b");
  223.             }
  224.             break;
  225.         case CTLR:    /* print line buffer */
  226.             if(ttyecho)
  227.                 printf("^R");
  228.             printf("\n");
  229.             if(ttyecho) {
  230.                 rp = linebuf ;
  231.                 while (rp < cp)
  232.                     putchar(*rp++) ;
  233.             }
  234.             break ;
  235.         case CTLU:    /* Line kill */
  236.             if(ttyecho) {
  237.                 while(cp != linebuf){
  238.                     cp--;
  239.                     printf("\b \b");
  240.                 }
  241.             } else
  242.                 cp = linebuf;
  243.             break;
  244.         case CTLV:
  245.             ttymode = TTY_LIT;
  246.             break;
  247.         case CTLW:    /* erase word */
  248.             seenprint = 0 ;    /* we haven't seen a printable char yet */
  249.             while (cp != linebuf) {
  250.                 cp--;
  251.                 if(ttyecho)
  252.                     printf("\b \b") ;
  253.                 if (isspace(*cp)) {
  254.                     if (seenprint)
  255.                         break ;
  256.                 }
  257.                 else
  258.                     seenprint = 1 ;
  259.             }
  260.             break ;
  261.         default:    /* Ordinary character */
  262.             *cp++ = c;
  263. #ifndef    AMIGA
  264.             /* ^Z apparently hangs the terminal emulators under
  265.              * DoubleDos and Desqview. I REALLY HATE having to patch
  266.              * around other people's bugslike this!!!
  267.              */
  268.             if (ttyecho && (c != CTLZ))
  269.                 putchar(c);
  270. #endif
  271.             if(cp >= &linebuf[LINESIZE]){
  272.                 cnt = cp - linebuf;
  273.                 cp = linebuf;
  274.             }
  275.             break;
  276.         }
  277.     }
  278.     if(cnt > 0)
  279.         *buf = linebuf;
  280.     else
  281.         *buf = '\0';
  282.     /*
  283.      * This isn't flow control in XON/XOFF sense.  Rather, it's
  284.      * a feature that holds output while the user is typing a
  285.      * line.  So if we're in the middle of a line, disable output
  286.      */
  287. #ifdef    FLOW
  288.     if(cp > linebuf)
  289.         ttyflow = 0;
  290.     else
  291.         ttyflow = 1;
  292. #endif
  293.     fflush(stdout);
  294.     return cnt;
  295. }
  296.